package com.dycn.posdashboard.services.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.apache.commons.lang.time.DateUtils;

import com.dycn.posdashboard.data.LiveUpTransactionInfo;
import com.dycn.posdashboard.data.PosTransactionData;
import com.dycn.posdashboard.data.ServicesResultObject;
import com.dycn.posdashboard.listener.SystemInitListener;
import com.dycn.posdashboard.services.CommonServices;
import com.dycn.posdashboard.services.LiveTransactionDataServices;
import com.dycn.posdashboard.services.PosTradeServices;
import com.dycn.posdashboard.util.DataCacheUtils;

public class LiveTransactionDataServicesImpl implements
		LiveTransactionDataServices {

	private Cache systmDataCache;
	private PosTradeServices posTradeServices;

	
	public PosTradeServices getPosTradeServices() {
		return posTradeServices;
	}

	public void setPosTradeServices(PosTradeServices posTradeServices) {
		this.posTradeServices = posTradeServices;
	}

	public Cache getSystmDataCache() {
		return systmDataCache;
	}

	public void setSystmDataCache(Cache systmDataCache) {
		this.systmDataCache = systmDataCache;
	}

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getLivePosTransactionInforOfBranch(
			String dbSource, String branchNo, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		
		return getLiveTransactionStatsInfor(branchNo,null,lastUpdateTime);
	}
	
	

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getLiveIncrementPosTransactionInfor(
			String dbSource, String branchNo, String merchantNo, int steps,
			Date lastUpdateSTime, Date lastUpdateETime) {
		// TODO Auto-generated method stub
		return getLiveTransactionStatsInfor(branchNo,merchantNo,steps,lastUpdateSTime,lastUpdateETime);
	}
	
	/**
	 * 
	 * @param branchNo
	 * @param merchantNo
	 * @param statsSteps 单位为毫秒
	 * @param lastUpdateCheckSTime
	 * @param lastUpdateCheckETime
	 * @return
	 * @throws ParseException 
	 */
	private ServicesResultObject<List<LiveUpTransactionInfo>> getLiveTransactionStatsInfor(String branchNo,String merchantNo, int statsSteps,Date lastUpdateCheckSTime,Date lastUpdateCheckETime){
		ServicesResultObject<List<LiveUpTransactionInfo>> someServicesResultObject=new ServicesResultObject<List<LiveUpTransactionInfo>>();
		someServicesResultObject.setResultMsg("");
		someServicesResultObject.setResultCode(CommonServices.RESULT_CODE_SUCCESS);
		someServicesResultObject.setReturnObj(null);
		Map<Long,LiveUpTransactionInfo> countMap=new HashMap<Long,LiveUpTransactionInfo>();
		
		SimpleDateFormat myFmt=new SimpleDateFormat("yyyyMMddHHmmss");
		String lastUpdateCheckSTimeStr=myFmt.format(lastUpdateCheckSTime);
		String lastUpdateCheckETimeStr=myFmt.format(lastUpdateCheckETime);
		
		
		Date tmp=lastUpdateCheckSTime;
		
		while(tmp.compareTo(lastUpdateCheckETime)<0){
			
			LiveUpTransactionInfo someLiveUpTransactionInfo=new LiveUpTransactionInfo();
			someLiveUpTransactionInfo.setDateTime(tmp);
			someLiveUpTransactionInfo.setTradeMoney(0);
			someLiveUpTransactionInfo.setTrades(0);
			countMap.put(Long.parseLong(myFmt.format(tmp)), someLiveUpTransactionInfo);
			
			tmp=DateUtils.addMilliseconds(tmp, statsSteps);
		}
		if(tmp.compareTo(lastUpdateCheckETime)>=0){
			
			LiveUpTransactionInfo someLiveUpTransactionInfo=new LiveUpTransactionInfo();
			someLiveUpTransactionInfo.setDateTime(tmp);
			someLiveUpTransactionInfo.setTradeMoney(0);
			someLiveUpTransactionInfo.setTrades(0);
			countMap.put(Long.parseLong(myFmt.format(tmp)), someLiveUpTransactionInfo);
			
			//tmp=DateUtils.addMilliseconds(tmp, statsSteps);
		}
		
		System.out.println("~~~getLiveTransactionStatsInfor~~~"+countMap.values().size());
		
		//Date currentDate=new Date();
		List<PosTransactionData> resultList=new ArrayList<PosTransactionData>();
		Element existedPosTransactionDatasCacheElement=this.systmDataCache.get(DataCacheUtils.LIVE_POS_TRADES_DATA);
		if(existedPosTransactionDatasCacheElement==null){
			someServicesResultObject.setReturnObj(new ArrayList<LiveUpTransactionInfo>(countMap.values()));
			return someServicesResultObject;
		}else{
			//LiveUpTransactionInfo
			List<PosTransactionData> cachePosTransactionDataList=(List<PosTransactionData>)existedPosTransactionDatasCacheElement.getValue();
			//Date specDteTime=null;
			boolean branchMatchedFlag=true;
			boolean merchantMatchedFlag=true;
			
			for(PosTransactionData somePosTransactionData:cachePosTransactionDataList){
				if(branchNo!=null&&!branchNo.trim().equals("")){
					if(somePosTransactionData.getBranchNo().equals(branchNo)){
						branchMatchedFlag=true;
					}else{
						branchMatchedFlag=false;
					}
				}
				
				if(merchantNo!=null&&!merchantNo.trim().equals("")){
					if(somePosTransactionData.getTerminalMerchantNo().equals(merchantNo)){
						merchantMatchedFlag=true;
					}else{
						merchantMatchedFlag=false;
					}
				}
				
				if(merchantMatchedFlag&&branchMatchedFlag
						&&somePosTransactionData.getTradeDate().compareTo(lastUpdateCheckSTime)>=0
						&&somePosTransactionData.getTradeDate().compareTo(lastUpdateCheckETime)<=0){
					
					resultList.add(somePosTransactionData);
					//specDteTime=DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.MINUTE);
					LiveUpTransactionInfo someLiveUpTransactionInfo=countMap.get(Long.parseLong(myFmt.format(somePosTransactionData.getTradeDate())));
					
					if(someLiveUpTransactionInfo==null){
						someLiveUpTransactionInfo=new LiveUpTransactionInfo();
						someLiveUpTransactionInfo.setDateTime(DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.SECOND));
						someLiveUpTransactionInfo.setTradeMoney(0.00);
						someLiveUpTransactionInfo.setTrades(0);
						//countMap.put(lastUpdateTime.getTime(), someLiveUpTransactionInfo);
					}
					System.out.println(" one acitve live1~~~~~~~"+someLiveUpTransactionInfo.getTrades());
					someLiveUpTransactionInfo.setTradeMoney(someLiveUpTransactionInfo.getTradeMoney()+somePosTransactionData.getTradeMoney());
					someLiveUpTransactionInfo.setTrades(someLiveUpTransactionInfo.getTrades()+1);
					System.out.println(" one acitve live2~~~~~~~"+someLiveUpTransactionInfo.getTrades());
					
				}
			}
			
//			if(cachePosTransactionDataList==null||cachePosTransactionDataList.size()==0||countMap.size()==0){
//				LiveUpTransactionInfo someLiveUpTransactionInfo=new LiveUpTransactionInfo();
//				
//				someLiveUpTransactionInfo.setDateTime(null);
//				someLiveUpTransactionInfo.setTradeMoney(0);
//				someLiveUpTransactionInfo.setTrades(0);
//				
//				//countMap.put(someLiveUpTransactionInfo.getDateTime().getTime(), someLiveUpTransactionInfo);
//			}

			
			//DateUtils.truncate(date, Calendar.SECOND);
		}
		
		ArrayList<LiveUpTransactionInfo> LiveUpTransactionInfoCollection=new ArrayList<LiveUpTransactionInfo>(countMap.values());
		
		Collections.sort(LiveUpTransactionInfoCollection, new Comparator<LiveUpTransactionInfo>(){

			@Override
			public int compare(LiveUpTransactionInfo arg0,
					LiveUpTransactionInfo arg1) {
				// TODO Auto-generated method stub
				return arg0.getDateTime().compareTo(arg1.getDateTime());
			}
			
		});
		
		someServicesResultObject.setReturnObj(new ArrayList<LiveUpTransactionInfo>(countMap.values()));
		return someServicesResultObject;
	}
	

	
	private ServicesResultObject<List<LiveUpTransactionInfo>> getLiveTransactionStatsInfor(String branchNo,String merchantNo, Date lastUpdateTime){
		ServicesResultObject<List<LiveUpTransactionInfo>> someServicesResultObject=new ServicesResultObject<List<LiveUpTransactionInfo>>();
		someServicesResultObject.setResultMsg("");
		someServicesResultObject.setResultCode(CommonServices.RESULT_CODE_SUCCESS);
		someServicesResultObject.setReturnObj(null);
		Map<Long,LiveUpTransactionInfo> countMap=new HashMap<Long,LiveUpTransactionInfo>();
		
		int liveUpdateInterval=SystemInitListener.LIVE_CHART_INTERVAL.intValue();
		
		//Date currentDate=new Date();
		List<PosTransactionData> resultList=new ArrayList<PosTransactionData>();
		Element existedPosTransactionDatasCacheElement=this.systmDataCache.get(DataCacheUtils.LIVE_POS_TRADES_DATA);
		if(existedPosTransactionDatasCacheElement==null){
			LiveUpTransactionInfo someLiveUpTransactionInfo=new LiveUpTransactionInfo();
			someLiveUpTransactionInfo.setDateTime(lastUpdateTime);
			someLiveUpTransactionInfo.setTradeMoney(0);
			someLiveUpTransactionInfo.setTrades(0);
			
			countMap.put(someLiveUpTransactionInfo.getDateTime().getTime(), someLiveUpTransactionInfo);
			someServicesResultObject.setReturnObj(new ArrayList<LiveUpTransactionInfo>(countMap.values()));
			
			return someServicesResultObject;
		}else{
			//LiveUpTransactionInfo
			List<PosTransactionData> cachePosTransactionDataList=(List<PosTransactionData>)existedPosTransactionDatasCacheElement.getValue();
			//Date specDteTime=null;
			boolean branchMatchedFlag=true;
			boolean merchantMatchedFlag=true;
			
			for(PosTransactionData somePosTransactionData:cachePosTransactionDataList){
				if(branchNo!=null&&!branchNo.trim().equals("")){
					if(somePosTransactionData.getBranchNo().equals(branchNo)){
						branchMatchedFlag=true;
					}else{
						branchMatchedFlag=false;
					}
				}
				
				if(merchantNo!=null&&!merchantNo.trim().equals("")){
					if(somePosTransactionData.getTerminalMerchantNo().equals(merchantNo)){
						merchantMatchedFlag=true;
					}else{
						merchantMatchedFlag=false;
					}
				}
				
				if(merchantMatchedFlag&&branchMatchedFlag
						&&somePosTransactionData.getTradeDate().compareTo(lastUpdateTime)<0
						&&somePosTransactionData.getTradeDate().compareTo(DateUtils.addMilliseconds(lastUpdateTime,-liveUpdateInterval))>=0){
					
					
					
					resultList.add(somePosTransactionData);
					//specDteTime=DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.MINUTE);
					LiveUpTransactionInfo someLiveUpTransactionInfo=countMap.get(lastUpdateTime.getTime());
					
					if(someLiveUpTransactionInfo==null){
						someLiveUpTransactionInfo=new LiveUpTransactionInfo();
						someLiveUpTransactionInfo.setDateTime(lastUpdateTime);
						someLiveUpTransactionInfo.setTradeMoney(0.00);
						someLiveUpTransactionInfo.setTrades(0);
						countMap.put(lastUpdateTime.getTime(), someLiveUpTransactionInfo);
					}
					System.out.println(" one acitve live1~~~~~~~"+someLiveUpTransactionInfo.getTrades());
					someLiveUpTransactionInfo.setTradeMoney(someLiveUpTransactionInfo.getTradeMoney()+somePosTransactionData.getTradeMoney());
					someLiveUpTransactionInfo.setTrades(someLiveUpTransactionInfo.getTrades()+1);
					System.out.println(" one acitve live2~~~~~~~"+someLiveUpTransactionInfo.getTrades());
					
				}
			}
			
			if(cachePosTransactionDataList==null||cachePosTransactionDataList.size()==0||countMap.size()==0){
				LiveUpTransactionInfo someLiveUpTransactionInfo=new LiveUpTransactionInfo();
				
				someLiveUpTransactionInfo.setDateTime(lastUpdateTime);
				someLiveUpTransactionInfo.setTradeMoney(0);
				someLiveUpTransactionInfo.setTrades(0);
				
				countMap.put(someLiveUpTransactionInfo.getDateTime().getTime(), someLiveUpTransactionInfo);
			}

			
			//DateUtils.truncate(date, Calendar.SECOND);
		}
		
		someServicesResultObject.setReturnObj(new ArrayList<LiveUpTransactionInfo>(countMap.values()));
		return someServicesResultObject;
	}

	@Override
	public ServicesResultObject<List<PosTransactionData>> getLivePosTransactionInforOfMerchant(
			String dbSource, String merchantNo, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ServicesResultObject<List<PosTransactionData>> getLivePosTransactionInforOfMerchant(
			String dbSource, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getLiveIncrementPosTransactionInforOfBranch(
			String dbSource, String branchNo, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		return getLiveTransactionStatsInfor(branchNo,null,lastUpdateTime);
	}

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getLiveIncrementPosTransactionInforOfMerchant(
			String dbSource, String merchantNo, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		return getLiveTransactionStatsInfor(null,merchantNo,lastUpdateTime);
	}

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getLiveIncrementPosTransactionInfor(
			String dbSource, Date lastUpdateTime) {
		// TODO Auto-generated method stub
		return getLiveTransactionStatsInfor(null,null,lastUpdateTime);
	}

	@Override
	public void updateLastPosTransactionInforOnCache(
			List<PosTransactionData> newPosTransactionDataList) {
		// TODO Auto-generated method stub
		Element existedPosTransactionDatasCacheElement=this.systmDataCache.get(DataCacheUtils.LIVE_POS_TRADES_DATA);
		
		if(existedPosTransactionDatasCacheElement==null){
			existedPosTransactionDatasCacheElement = new Element(DataCacheUtils.LIVE_POS_TRADES_DATA, new ArrayList<PosTransactionData>());
			//existedPosTransactionDatasCacheElement.setTimeToLive(150);//150秒后自动清除 也就是2分半后自动删除数据
			systmDataCache.put(existedPosTransactionDatasCacheElement);
		}
		List<PosTransactionData> livePosTransactionDatas=(List<PosTransactionData>)existedPosTransactionDatasCacheElement.getValue();
		
//		List<PosTransactionData> dest=new ArrayList<PosTransactionData>();  
//		Collections.copy(dest, livePosTransactionDatas);
//		dest.addAll(newPosTransactionDataList);
//		HashSet<PosTransactionData> h = new HashSet<PosTransactionData>(DataCacheUtils.getLastPosTransactionDatas());  
//		dest.clear();
//		dest.addAll(h); 
		
		Date currentDate=new Date();
		List<PosTransactionData> newlivePosTransactionDataList=new ArrayList<PosTransactionData>();
		for(PosTransactionData somePosTransactionData:newPosTransactionDataList){
			if(DateUtils.addMinutes(somePosTransactionData.getTradeDate(), 2).after(currentDate)){
				newlivePosTransactionDataList.add(somePosTransactionData);
			}else{
				continue;
			}
		}
		//livePosTransactionDatas.addAll(newlivePosTransactionDataList);
		
		//清楚过期2分钟的缓存数据
		Collections.sort(livePosTransactionDatas,new Comparator<PosTransactionData>(){

			@Override
			public int compare(PosTransactionData arg0, PosTransactionData arg1) {
				// TODO Auto-generated method stub
				return arg0.getTradeDate().compareTo(arg1.getTradeDate());
			}
			
		});
		int willRemoveEndIndex=0;
		for(PosTransactionData smePosTransactionData:livePosTransactionDatas){
			if(DateUtils.addMinutes(smePosTransactionData.getTradeDate(), 2).after(currentDate)){
				break;
			}else{
				willRemoveEndIndex++;
			}
		}
		
		livePosTransactionDatas=livePosTransactionDatas.subList(willRemoveEndIndex,livePosTransactionDatas.size());

		livePosTransactionDatas.addAll(newlivePosTransactionDataList);
		

	}

	@Override
	public ServicesResultObject<List<LiveUpTransactionInfo>> getRecentLiveIncrementPosTransactionInfor(
			String dbSource, String branchNo, String merchantNo, String cardNo,
			Date lastUpdateSTime, Date lastUpdateETime) {
		// TODO Auto-generated method stub
		ServicesResultObject<List<LiveUpTransactionInfo>> someServicesResultObject=new ServicesResultObject<List<LiveUpTransactionInfo>>();
		someServicesResultObject.setResultMsg("");
		someServicesResultObject.setResultCode(CommonServices.RESULT_CODE_SUCCESS);
		someServicesResultObject.setReturnObj(null);
		
		ServicesResultObject<List<PosTransactionData>> getRecentPosTraServiceResult=this.posTradeServices.getRecentPosTransactionDataListBy(dbSource, branchNo, merchantNo, 
				cardNo, lastUpdateSTime, 10*60);
		List<PosTransactionData> recentTradeList=getRecentPosTraServiceResult.getReturnObj();
		//以SystemInitListener.LIVE_CHART_INTERVAL为单位group数据
		
		Map<Long,LiveUpTransactionInfo> countMap=new HashMap<Long,LiveUpTransactionInfo>();
		
		SimpleDateFormat myFmt=new SimpleDateFormat("yyyyMMddHHmmss");
		
		Date startTime=lastUpdateSTime;
		Date endTime=DateUtils.addSeconds(lastUpdateSTime,10*60);
		
		Date tmp=startTime;
		LiveUpTransactionInfo someLiveUpTransactionInfo=null;
		
		someLiveUpTransactionInfo=new LiveUpTransactionInfo();
		someLiveUpTransactionInfo.setDateTime(DateUtils.truncate(startTime, Calendar.SECOND));
		someLiveUpTransactionInfo.setTradeMoney(0);
		someLiveUpTransactionInfo.setTrades(0);
		countMap.put(Long.parseLong(myFmt.format(startTime)), someLiveUpTransactionInfo);
		
		while(tmp.compareTo(endTime)<0){
			
			someLiveUpTransactionInfo=new LiveUpTransactionInfo();
			someLiveUpTransactionInfo.setDateTime(DateUtils.truncate(tmp, Calendar.SECOND));
			someLiveUpTransactionInfo.setTradeMoney(0);
			someLiveUpTransactionInfo.setTrades(0);
			countMap.put(Long.parseLong(myFmt.format(tmp)), someLiveUpTransactionInfo);
			
			tmp=DateUtils.addMilliseconds(tmp, SystemInitListener.LIVE_CHART_INTERVAL.intValue());
		}
		
		someLiveUpTransactionInfo=new LiveUpTransactionInfo();
		someLiveUpTransactionInfo.setDateTime(DateUtils.truncate(endTime, Calendar.SECOND));
		someLiveUpTransactionInfo.setTradeMoney(0);
		someLiveUpTransactionInfo.setTrades(0);
		countMap.put(Long.parseLong(myFmt.format(endTime)), someLiveUpTransactionInfo);

		
		List<Long> keyList=new ArrayList<Long>(countMap.keySet());
		Collections.sort(keyList, new Comparator<Long>(){

			@Override
			public int compare(Long arg0,
					Long arg1) {
				// TODO Auto-generated method stub
				if(arg0.longValue()-arg1.longValue()<0){
					return -1;
				}else if(arg0.longValue()-arg1.longValue()==0){
					return 0;
				}else{
					return 1;
				}
			}
			
		});
		
		List<Long> destTmpKeyList=new ArrayList<Long>();
		if(recentTradeList!=null&&recentTradeList.size()!=0){
			for(PosTransactionData somePosTransactionData:recentTradeList){
				long timeKey=Long.parseLong(myFmt.format(DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.SECOND)));
				
//				destTmpKeyList=new ArrayList<Long>();
//				Collections.copy(destTmpKeyList, keyList);
//				if(keyList.indexOf(timeKey)!=-1){
//					keyList.add(timeKey);
//				}
				
				someLiveUpTransactionInfo=countMap.get(timeKey);
				
				if(someLiveUpTransactionInfo==null){
					someLiveUpTransactionInfo=new LiveUpTransactionInfo();
					someLiveUpTransactionInfo.setDateTime(DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.SECOND));
					someLiveUpTransactionInfo.setTradeMoney(0.00);
					someLiveUpTransactionInfo.setTrades(0);
					countMap.put(Long.parseLong(myFmt.format(DateUtils.truncate(somePosTransactionData.getTradeDate(), Calendar.SECOND))), someLiveUpTransactionInfo);
				}
				
				System.out.println(" one acitve live1~~~~~~~"+someLiveUpTransactionInfo.getTrades());
				someLiveUpTransactionInfo.setTradeMoney(someLiveUpTransactionInfo.getTradeMoney()+somePosTransactionData.getTradeMoney());
				someLiveUpTransactionInfo.setTrades(someLiveUpTransactionInfo.getTrades()+1);
				System.out.println(" one acitve live2~~~~~~~"+someLiveUpTransactionInfo.getTrades());

			}
		}
		
		List<LiveUpTransactionInfo> someLiveUpTransactionInfoList=new ArrayList<LiveUpTransactionInfo>(countMap.values());
		Collections.sort(someLiveUpTransactionInfoList, new Comparator<LiveUpTransactionInfo>(){

			@Override
			public int compare(LiveUpTransactionInfo arg0,
					LiveUpTransactionInfo arg1) {
				// TODO Auto-generated method stub
				return arg0.getDateTime().compareTo(arg1.getDateTime());
			}
			
		});
		someServicesResultObject.setReturnObj(someLiveUpTransactionInfoList);
		
		return someServicesResultObject;
	}

}
